#import "MapPOISearchView.h"

// Singleton instance of MapPOISearchView
static MapPOISearchView* sharedMapPOISearchView = nil;

/**
 * A MapPOISearchView is an object representing the view that 
 * displays a list of points of interest by which to search for 
 * on the map.
 *
 * A MapPOISearchDelegate must be set to respond to events from
 * the map POI search viewer.
 *
 * @author      James Lin
 * @version     1.0.3
 * @since       1.0.3
 * @see         GenericSearchView
 * @see         MapPOISearchDelegate
 */
@implementation MapPOISearchView

/**
 * Retrieve the shared instance of the map POI search view.
 *
 * @return  the shared instance of MapPOISearchView
 */
+ (MapPOISearchView*)sharedMapPOISearchView {
	@synchronized(self) {
		if (sharedMapPOISearchView == nil) {
			sharedMapPOISearchView = [[MapPOISearchView alloc] init];
		}
		return sharedMapPOISearchView;
	}
}

/**
 * Allocate the map point of interest search view.
 *
 * @return  the newly allocated shared instance of MapPOISearchView
 */
+ (id) alloc {
	@synchronized(self) {
		sharedMapPOISearchView = [super alloc];
		return sharedMapPOISearchView;
	}
}

/**
 * Retrieve a copy of the map point of interest search view.
 *
 * @return  the shared instance of MapPOISearchView
 */
+ (id) copy {
	@synchronized(self) {
		return sharedMapPOISearchView;
	}
}

/**
 * Get the delegate handling events from this view.
 *
 * @return  the delegate handling events from this view
 * @see     MapGenericSearchView
 */
- (id<MapPOISearchDelegate>)delegate {
	return delegate;
}

/**
 * Set the delegate handling events from this view.
 *
 * @param theDelegate  the delegate handling events from this view
 * @see                MapGenericSearchView
 */
- (void)setDelegate:(id)theDelegate {
	delegate = theDelegate;
}

/**
 * Display the table listing of points of interest in a new view.
 *
 * Pushes this view onto the navigation controller stack of the parent
 * view. Upon tapping the back button, the view is automatically 
 * popped off the top of the navigation stack.
 *
 * @param pois           the list of points of interest to display
 * @param navController  the navigation controller of the parent view
 */
- (void)displayViewWithPOIs:(NSArray*)pois 
			  navController:(UINavigationController*)navController {
	// Create the table of points of interest
	if (poiTableView) {
		[poiTableView release];
	}
	poiTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 
																 VIEW_WIDTH, 
																 VIEW_HEIGHT-44) 
												style:UITableViewStylePlain];
	poiTableView.backgroundColor = [UIColor lightGrayColor];
	poiTableView.separatorColor = [UIColor whiteColor];
	poiTableView.tableFooterView = [[[UIView alloc] 
									 initWithFrame:CGRectMake(0, 0, 1, 60)] autorelease];
	[poiTableView setRowHeight:POI_CELL_HEIGHT];
	[poiTableView setDelegate:self];
	[poiTableView setDataSource:self];
	
	self.navigationItem.title = @"Points of Interest";
	parentNav = navController;
	
	// Populate the table with points of interest
	if (poiList) {
		[poiList release];
	}
	poiList = [[NSArray alloc] initWithArray:pois];
	[poiTableView reloadData];
	
	// Prepare the array of selected points of interest
	if (selectedPois) {
		[selectedPois release];
	}
	selectedPois = [[NSMutableArray array] retain];
	
	// Set up the toolbar for this view
	if (poiToolbar) {
		[poiToolbar release];
	}
	poiToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, VIEW_HEIGHT-44, 
															 VIEW_WIDTH, 44)];
	poiToolbar.barStyle = UIBarStyleBlack;
	
	// Create the toolbar buttons
	UIBarButtonItem* selAllButton = [[UIBarButtonItem alloc] initWithTitle:@"Select All"
																	 style:UIBarButtonItemStyleBordered 
																	target:self
																	action:@selector(selectAllPOI)];
	UIBarButtonItem* deselAllButton = [[UIBarButtonItem alloc] initWithTitle:@"Deselect All"
																	   style:UIBarButtonItemStyleBordered 
																	  target:self
																	  action:@selector(deselectAllPOI)];
	UIBarButtonItem* spacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace 
																			target:nil 
																			action:nil];
	[poiToolbar setItems:[NSArray arrayWithObjects:spacer, selAllButton, deselAllButton, spacer, nil] 
				animated:YES];
	[selAllButton release];
	[deselAllButton release];
	[spacer release];
	
	// Create the search button
	UIBarButtonItem* rightButton = [[UIBarButtonItem alloc] initWithTitle:@"Search" 
																	style:UIBarButtonItemStyleDone 
																   target:self 
																   action:@selector(initSearch)];
	[self.navigationItem setRightBarButtonItem:rightButton animated:YES];
	[rightButton release];
	
	// Display the table of points of interest with its toolbar
	[self.view addSubview:poiTableView];
	[self.view addSubview:poiToolbar];
	[parentNav pushViewController:self animated:YES];
}

/**
 * Get the number of rows in the table view.
 */
- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section {
	return poiList.count;
}

/**
 * Populate a table view cell in the table view with content.
 */
- (UITableViewCell*)tableView:(UITableView*)tableView 
		cellForRowAtIndexPath:(NSIndexPath*)indexPath {
	static NSString* CellIdentifier = @"POICell";
	UITableViewCell* cell = [poiTableView dequeueReusableCellWithIdentifier:CellIdentifier];
	
	if (cell == nil) {
		// Create an empty reusable cell for performance sake
		cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
									   reuseIdentifier:CellIdentifier] autorelease];
		
		cell.textLabel.font = [UIFont boldSystemFontOfSize:13.5];
		
		// Set the background color for the cell when selected
		UIView* cellView = [[[UIView alloc] init] autorelease];
		cellView.backgroundColor = [UIColor darkGrayColor];
		cell.selectedBackgroundView = cellView;
	}
	
	// Determine whether selected and set the accessory view of the cell
	if ([selectedPois containsObject:[poiList objectAtIndex:indexPath.row]]) {
		cell.accessoryType = UITableViewCellAccessoryCheckmark;
	} else {
		cell.accessoryType = UITableViewCellAccessoryNone;
	}
	
	// Refresh the label content of the cell
	cell.textLabel.text = [poiList objectAtIndex:indexPath.row];
	
	return cell;
}

/**
 * Search for the point of interest that is selected.
 */
- (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
	if ([selectedPois containsObject:[poiList objectAtIndex:indexPath.row]]) {
		[selectedPois removeObject:[poiList objectAtIndex:indexPath.row]];
	} else {
		[selectedPois addObject:[poiList objectAtIndex:indexPath.row]];
	}
	[poiTableView reloadData];
}

/**
 * Initiate the search request.
 */
- (void)initSearch {
	if ([selectedPois count] > 0) {
		[delegate searchRequestByPOIs:selectedPois];
		[parentNav popViewControllerAnimated:YES];
	} else {
		NSString* msg = @"Please select at least one filter.";
		[GraphicsUtilities displayAlertWithTitle:msg 
										 message:nil];
	}
}

/**
 * Select all points of interest.
 */
- (void)selectAllPOI {
	[selectedPois removeAllObjects];
	[selectedPois addObjectsFromArray:poiList];
	[poiTableView reloadData];
}

/**
 * Deselect all points of interest.
 */
- (void)deselectAllPOI {
	[selectedPois removeAllObjects];
	[poiTableView reloadData];
}

/**
 * Animate the view when it appears.
 */
- (void)viewDidAppear:(BOOL)animated {
	[super viewDidAppear:YES];
}

/**
 * Deallocate the point of interest search view.
 */
- (void)dealloc {
	delegate = nil;
	[poiList release], poiList = nil;
	[selectedPois release], selectedPois = nil;
	[poiToolbar release], poiToolbar = nil;
	[poiTableView release], poiTableView = nil;
	parentNav = nil;
	[sharedMapPOISearchView release];
	sharedMapPOISearchView = nil;
    [super dealloc];
}

@end